package resource

import (
	"project-info/src/handle/common"
	"project-info/src/handle/response"
	"project-info/src/model"
	routeReq "project-info/src/router/req"
	"gorm.io/gorm"

	"project-info/src/lib")

type PageResourceReq struct {
	Query string `json:"query"`
	Type  int8   `json:"type"`
	common.PageRequest
}

type BindReq struct {
	UserIds []uint64 `json:"userIds"`
	RoleIds []uint64 `json:"roleIds"`
	PrivilegeEntity
}

type PrivilegeEntity struct {
	ResourceId uint64 `json:"resourceId"`
	Type       int8   `json:"type"`
}

type ResourcePrivilegeRes struct {
	UserIds []uint   `json:"userIds"`
	RoleIds []uint64 `json:"roleIds"`
	PrivilegeEntity
}

type GetResourceOptionsReq struct {
	Types []int8 `json:"types"`
}

// AddResource 添加资源
func AddResource(c *lib.GinContext) error {
	// 1.解析参数
	var resource *model.Resource
	if err := c.Bind(&resource); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}
	//2.检验resource是否存在
	var count int64
	db := model.DB().Model(&model.Resource{}).Where("name = ? and type = ?", resource.Name, resource.Type)
	if err := db.Count(&count).Error; err != nil {
		return response.JsonFail(c, "查询失败")
	}

	if count > 0 && resource.Id == 0 {
		return response.JsonFail(c, "资源已存在")
	}

	// 3.保存数据
	if resource.Id != 0 {
		if err := model.DB().Save(resource).Error; err != nil {
			return response.JsonFail(c, "保存失败")
		}
	} else {
		if err := model.DB().Create(resource).Error; err != nil {
			return response.JsonFail(c, "保存失败")
		}
	}
	return response.JsonOk(c, resource, "保存成功")
}

// PageResource 分页查询资源
func PageResource(c *lib.GinContext) error {
	var req *PageResourceReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}

	var resources []*model.Resource
	var total int64
	db := model.DB().Model(&model.Resource{})
	db = db.Where("type = ?", req.Type)
	if req.Query != "" {
		db = db.Where("name like ?", "%"+req.Query+"%")
	}
	if err := db.Count(&total).Order("id desc").Offset((req.Page - 1) * req.Size).Limit(req.Size).Find(&resources).Error; err != nil && err != gorm.ErrRecordNotFound {
		return response.JsonFail(c, "查询数据库失败")
	}
	return response.JsonOk(c, map[string]interface{}{"records": resources, "total": total}, "查询成功")
}

// DeleteResource 删除资源
func DeleteResource(c *lib.GinContext) error {
	var resource *model.Resource
	if err := c.Bind(&resource); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}

	db := model.DB()
	err := db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Delete(&model.Resource{}, resource.Id).Error; err != nil {
			return err
		}
		if err := tx.Delete(&model.ResourceUser{}, "resource_id = ?", resource.Id).Error; err != nil {
			return err
		}
		if err := tx.Delete(&model.ResourceRole{}, "resource_id = ?", resource.Id).Error; err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		return response.JsonFail(c, "删除失败")
	}
	return response.JsonOk(c, nil, "删除成功")
}

// GetResourcePrivilege 获取资源权限
func GetResourcePrivilege(c *lib.GinContext) error {
	var req *PrivilegeEntity
	if err := c.Bind(&req); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}

	var userIds []uint
	model.DB().Model(&model.ResourceUser{}).Where("resource_id = ? and resource_type = ?", req.ResourceId, req.Type).Pluck("user_id", &userIds)

	var roleIds []uint64
	model.DB().Model(&model.ResourceRole{}).Where("resource_id = ? and resource_type = ?", req.ResourceId, req.Type).Pluck("role_id", &roleIds)

	resourcePrivilegeRes := &ResourcePrivilegeRes{
		UserIds: userIds,
		RoleIds: roleIds,
		PrivilegeEntity: PrivilegeEntity{
			ResourceId: req.ResourceId,
			Type:       req.Type,
		},
	}
	return response.JsonOk(c, resourcePrivilegeRes, "查询成功")
}

// BindResource 绑定资源
func BindResource(c *lib.GinContext) error {
	// 1.解析参数
	var bindReq *BindReq
	if err := c.Bind(&bindReq); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}
	// 从bindReq中获取resourceUser和resourceRole
	var resourceUser []*model.ResourceUser
	var resourceRole []*model.ResourceRole
	for _, userId := range bindReq.UserIds {
		resourceUser = append(resourceUser, &model.ResourceUser{UserId: userId, ResourceId: bindReq.ResourceId, ResourceType: bindReq.Type})
	}
	for _, roleId := range bindReq.RoleIds {
		resourceRole = append(resourceRole, &model.ResourceRole{RoleId: roleId, ResourceId: bindReq.ResourceId, ResourceType: bindReq.Type})
	}

	err := model.DB().Transaction(func(tx *gorm.DB) error {
		// 2.删除数据
		if err := tx.Where("resource_id = ?", bindReq.ResourceId).Delete(&model.ResourceUser{}).Error; err != nil {
			return err
		}

		if err := tx.Where("resource_id = ?", bindReq.ResourceId).Delete(&model.ResourceRole{}).Error; err != nil {
			return err
		}

		// 3.保存数据
		if len(resourceUser) > 0 {
			if err := tx.Create(&resourceUser).Error; err != nil {
				return err
			}
		}
		if len(resourceRole) > 0 {
			if err := tx.Create(&resourceRole).Error; err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return response.JsonFail(c, "绑定失败")
	}
	return response.JsonOk(c, nil, "绑定成功")
}

// GetResourceOptions 获取资源选项
func GetResourceOptions(c *lib.GinContext) error {
	var req GetResourceOptionsReq
	if err := c.Bind(&req); err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "参数解析错误")
	}

	var resources []*model.Resource
	db := model.DB()
	db, err := routeReq.HandleResourceDataPermission(c, req.Types, db)
	if err != nil {
		c.Logger().Error(err.Error())
		return response.JsonFail(c, "数据权限校验出错")
	}

	if err := db.Where("type in ?", req.Types).Find(&resources).Error; err != nil {
		return response.JsonFail(c, "查询失败")
	}

	var res = make(map[int8][]common.OptionRes)
	for _, resource := range resources {
		if _, ok := res[resource.Type]; !ok {
			res[resource.Type] = make([]common.OptionRes, 0)
		}
		res[resource.Type] = append(res[resource.Type], common.OptionRes{Value: resource.Id, Label: resource.Name})
	}
	return response.JsonOk(c, res, "查询成功")
}
